/*
 * Copyright 2011 Noctarius (Christoph Engelbert)
 * Part of www.sourceprojects.org 
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may 
 * not use this file except in compliance with the License. 
 * You may obtain a copy of the License at 
 *    http://www.apache.org/licenses/LICENSE-2.0 
 *
 * Unless required by applicable law or agreed to in writing, software 
 * distributed under the License is distributed on an "AS IS" BASIS, 
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 * See the License for the specific language governing permissions and 
 * limitations under the License.
 */
package org.sourceprojects.cappadocia.builder;

import java.io.IOException;
import java.util.Collection;

import org.sourceprojects.cappadocia.ClassInfo;
import org.sourceprojects.cappadocia.ClassPool;
import org.sourceprojects.cappadocia.ClassQuery;
import org.sourceprojects.cappadocia.ClassQueryException;
import org.sourceprojects.cappadocia.org.josql.Query;
import org.sourceprojects.cappadocia.org.josql.QueryExecutionException;
import org.sourceprojects.cappadocia.org.josql.QueryParseException;
import org.sourceprojects.cappadocia.org.josql.QueryResults;

public abstract class ClassQueryBuilder {
	private static final String ClassInfoCanonicalName = ClassInfo.class
			.getCanonicalName();

	protected ClassAttributeSelector where() {
		return new ClassAttributeSelectorImpl(null);
	}

	protected abstract ClassAttributeConstraintSelector configure();

	public ClassQuery build() {
		try {
			final StringBuilder builder = new StringBuilder("SELECT * FROM ")
					.append(ClassInfoCanonicalName).append(" WHERE ");

			final Query query = new Query();
			query.addFunctionHandler(new CustomJoSQLFunctions());
			query.parse(builder.append(configure().toQuery()).toString());

			return new ClassQuery() {

				@Override
				@SuppressWarnings("unchecked")
				public Collection<ClassInfo> list(final ClassPool classPool) {
					try {
						classPool.refreshClassCache();

						final QueryResults results = query.execute(classPool
								.getClassCache());

						return results.getResults();

					} catch (final IOException e) {
						throw new ClassQueryException(
								"Query could not be executed", e);

					} catch (final QueryExecutionException e) {
						throw new ClassQueryException(
								"Query could not be executed", e);
					}
				}
			};

		} catch (final QueryParseException e) {
			throw new ClassQueryException("Query could not be compiled", e);
		}
	}
}
